package com.niiwoo.civet.account.service.local.check.job.apiservice.recharge;

import com.alibaba.dubbo.config.annotation.Service;
import com.dangdang.ddframe.rdb.sharding.api.HintManager;
import com.dangdang.ddframe.rdb.sharding.hint.HintManagerHolder;
import com.github.pagehelper.PageHelper;
import com.niiwoo.civet.account.dao.entity.AccountBase;
import com.niiwoo.civet.account.dao.entity.AccountCheckingException;
import com.niiwoo.civet.account.dao.entity.AccountCheckingRecharge;
import com.niiwoo.civet.account.dao.entity.AccountCheckingWithholdOrder;
import com.niiwoo.civet.account.dao.entity.BankCard;
import com.niiwoo.civet.account.dao.entity.RechargeOrder;
import com.niiwoo.civet.account.dao.mapper.AccountBaseMapperExt;
import com.niiwoo.civet.account.dao.mapper.AccountCheckingRechargeMapperExt;
import com.niiwoo.civet.account.dao.mapper.AccountCheckingWithholdOrderMapper;
import com.niiwoo.civet.account.dao.mapper.BankCardMapperExt;
import com.niiwoo.civet.account.dao.mapper.RechargeOrderMapperExt;
import com.niiwoo.civet.account.dto.request.AccountCheckingRechargeRequestDTO;
import com.niiwoo.civet.account.service.local.check.job.api.CheckDetailService;
import com.niiwoo.civet.account.service.local.check.job.api.ParseService;
import com.niiwoo.civet.account.service.local.check.job.enums.BankBizTypeEnum;
import com.niiwoo.civet.account.service.local.check.job.enums.CheckExceptionStatusEnum;
import com.niiwoo.civet.account.service.local.check.job.enums.CheckResultEnum;
import com.niiwoo.civet.account.service.local.check.job.enums.HandleTypeEnum;
import com.niiwoo.civet.account.service.local.check.job.util.DateUtil;
import com.niiwoo.civet.base.enums.CommonOrderStatusEnum;
import com.niiwoo.tripod.base.component.PrivacyMasks;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Service(version = "1.0.0")
public class RechargeCheckDetailServiceImpl
        implements ParseService<AccountCheckingRecharge>, CheckDetailService<AccountCheckingRecharge> {

    @Autowired
    private AccountCheckingRechargeMapperExt accountCheckingRechargeMapperExt;
    @Autowired
    private RechargeOrderMapperExt rechargeOrderMapperExt;
    @Autowired
    private AccountCheckingWithholdOrderMapper accountCheckingWithholdOrderMapper;
    @Autowired
    private AccountBaseMapperExt accountBaseMapperExt;
    @Autowired
    private BankCardMapperExt bankCardMapperExt;
    @Autowired
    private PrivacyMasks privacyMasks;


    @Override
    public List<AccountCheckingRecharge> load(Long checkRecordId, int page, int pageSize) {
    	// shardingjdbc 强制走主库
		if (!HintManagerHolder.isMasterRouteOnly()) {
            HintManagerHolder.clear();
            HintManager hintManager = HintManager.getInstance();
            hintManager.setMasterRouteOnly();
        }
		log.debug("is matster route only : {}", HintManagerHolder.isMasterRouteOnly());

        AccountCheckingRechargeRequestDTO accountCheckingRechargeRequestDTO = new AccountCheckingRechargeRequestDTO();
        PageHelper.startPage(page, pageSize);
        accountCheckingRechargeRequestDTO.setCheckingRecordId(checkRecordId);
        accountCheckingRechargeRequestDTO.setStatus(Byte.valueOf("1"));
        List<AccountCheckingRecharge> accountCheckingRecharges = (List<AccountCheckingRecharge>) this.accountCheckingRechargeMapperExt.queryCheckingRechargePage(accountCheckingRechargeRequestDTO);
        return accountCheckingRecharges;
    }

    @Override
    public AccountCheckingException check(AccountCheckingRecharge accountCheckingRecharge, String checkDate) {
        RechargeOrder rechargeOrder = rechargeOrderMapperExt.queryRechargeOrderByRequestNo(accountCheckingRecharge.getPlatformRequestNo());
        if (rechargeOrder != null) {
        	return checkRechargeOrder(accountCheckingRecharge, rechargeOrder, checkDate);
        } else {
        	return checkWithholdOrder(accountCheckingRecharge, checkDate);
        }
    }
    
    private AccountCheckingException checkWithholdOrder(AccountCheckingRecharge accountCheckingRecharge,
                                                        String checkDate) {
    	List<AccountCheckingWithholdOrder> list = accountCheckingWithholdOrderMapper.selectByRequestNo(accountCheckingRecharge.getPlatformRequestNo());
    	
    	if (list == null || list.isEmpty()) {
			return getPlatformNoRecordException(accountCheckingRecharge, checkDate);
		}
    	AccountCheckingWithholdOrder withholdOrder = list.get(0);
		StringBuffer buf = new StringBuffer();
		boolean isTrue = true;

        AccountCheckingException exp = new AccountCheckingException();
		// 比对字段：1. 金额；2. 状态；
		if (accountCheckingRecharge.getAmount().compareTo(withholdOrder.getAmount()) != 0) {
			isTrue = false;
			buf.append("账单金额不等；");
            exp.setHandleType(HandleTypeEnum.BOTH_ERROR.getIndex());
		}
		if (withholdOrder.getStatus() != 2) { //2-成功
			isTrue = false;
			buf.append("代扣单状态异常；");
            exp.setHandleType(HandleTypeEnum.BOTH_ERROR.getIndex());
		}
        if( !withholdOrder.getPayChannelCode().equals(accountCheckingRecharge.getPayChannelCode())){
            isTrue = false;
            buf.append(CheckResultEnum.PAY_CHANNEL_ERROR.getName());
            exp.setHandleType(HandleTypeEnum.BOTH_ERROR.getIndex());
        }

        if( !withholdOrder.getBankCode().equals(accountCheckingRecharge.getBankCode())){
            isTrue = false;
            buf.append(CheckResultEnum.BANK_CORD_ERROR.getName());
            exp.setHandleType(HandleTypeEnum.NORMAL.getIndex());
        }
        BankCard bankCard = bankCardMapperExt.selectByPrimaryKey(withholdOrder.getBankCardId());
		if( null == bankCard){
            isTrue = false;
		    buf.append(CheckResultEnum.BANK_CARD_IS_NULL.getName());
            exp.setHandleType(HandleTypeEnum.BOTH_ERROR.getIndex());
        }
        String bankCardNO = privacyMasks.decryptPrivacy(bankCard.getBankAccountNo());
        if( !bankCardNO.substring(bankCardNO.length()-4,bankCardNO.length()).equals(accountCheckingRecharge.getBankAccountNo().substring(accountCheckingRecharge.getBankAccountNo().length() - 4 ,accountCheckingRecharge.getBankAccountNo().length()))){
            isTrue = false;
            buf.append(CheckResultEnum.BANK_CORD_NO_ERROR.getName());
            exp.setHandleType(HandleTypeEnum.NORMAL.getIndex());
        }
        //平台用户编号验证
        {
            AccountBase accountBase = accountBaseMapperExt.selectByPrimaryKey(withholdOrder.getAccountId());
            if( !accountCheckingRecharge.getPlatformUserNo().equals(accountBase.getAccountNo())){
                isTrue = false;
                buf.append(CheckResultEnum.PLATFORM_USER_NO_ERROR.getName());
                exp.setHandleType(HandleTypeEnum.BOTH_ERROR.getIndex());
            }
        }
		
		if (!isTrue) {
			exp.setBillDate(checkDate);
			exp.setBusinessType(BankBizTypeEnum.WITHHOLD.getCode()); //99-代扣充值
			//exp.setHandleType(HandleTypeEnum.BOTH_ERROR.getIndex()); // 1银行有记录，平台无记录
			exp.setCreateTime(new Date());
			exp.setCheckingRecordId(accountCheckingRecharge.getCheckingRecordId());
			exp.setCheckingDetailId(accountCheckingRecharge.getId());
			exp.setPlatformRecordId(withholdOrder.getId());
			exp.setCheckingType((byte) 1); // 1充值文件
			exp.setDescription(buf.toString());
			exp.setStatus(CheckExceptionStatusEnum.UNCONFIRM.getCode());
			exp.setOrderNo(accountCheckingRecharge.getRechargeOrderNo());

			return exp;
		}

		return null;
	}
    
    private AccountCheckingException getPlatformNoRecordException(AccountCheckingRecharge transation,
                                                                  String checkDate) {
		AccountCheckingException exp = new AccountCheckingException();
		exp.setBillDate(checkDate);
		exp.setBusinessType(transation.getBusinessType());
		exp.setHandleType(HandleTypeEnum.BACK_ONLY.getIndex()); // 1银行有记录，平台无记录
		exp.setCreateTime(new Date());
		exp.setCheckingRecordId(transation.getCheckingRecordId());
		exp.setCheckingDetailId(transation.getId());
		exp.setCheckingType((byte) 1); // 1充值文件
		exp.setDescription(CheckResultEnum.NO_RECORD.getName());
		exp.setStatus(CheckExceptionStatusEnum.UNCONFIRM.getCode());
		exp.setOrderNo(transation.getRechargeOrderNo());

		return exp;
	}

	private AccountCheckingException checkRechargeOrder(AccountCheckingRecharge accountCheckingRecharge, RechargeOrder rechargeOrder, String checkDate) {
    	 AccountCheckingException accountCheckingException = new AccountCheckingException();
         accountCheckingRecharge.setStatus(Byte.valueOf("2"));

         List<String> errors = new ArrayList<String>();
         //判断平台是否有记录
         if( null == rechargeOrder ) {
             accountCheckingException.setHandleType(HandleTypeEnum.BACK_ONLY.getIndex());
             errors.add(CheckResultEnum.NO_RECORD.getName());
             return submit(accountCheckingRecharge,accountCheckingException,rechargeOrder,errors,checkDate);
         }
         if( !rechargeOrder.getStatus().equals(CommonOrderStatusEnum.SUCCESS.getValue())){
             errors.add(CheckResultEnum.PROCCESS_STATUS.getName());
             accountCheckingException.setHandleType(HandleTypeEnum.BOTH_ERROR.getIndex());
         }
         if( !rechargeOrder.getAmount().equals(accountCheckingRecharge.getAmount()) ){
             errors.add(CheckResultEnum.REAL_AMOUNT_NOT_EQUAL.getName());
             accountCheckingException.setHandleType(HandleTypeEnum.BOTH_ERROR.getIndex());
         }
         if( !rechargeOrder.getPayChannelCode().equals(accountCheckingRecharge.getPayChannelCode())){
             errors.add(CheckResultEnum.PAY_CHANNEL_ERROR.getName());
             accountCheckingException.setHandleType(HandleTypeEnum.BOTH_ERROR.getIndex());
         }
         if(rechargeOrder.getRechargeWay().equals((byte)2)){
             if( !rechargeOrder.getBankCode().equals(accountCheckingRecharge.getBankCode())){
                 errors.add(CheckResultEnum.BANK_CORD_ERROR.getName());
                 accountCheckingException.setHandleType(HandleTypeEnum.NORMAL.getIndex());
             }
             BankCard bankCard = bankCardMapperExt.selectByPrimaryKey(rechargeOrder.getBankCardId());
             if( null == bankCard ){
                 errors.add(CheckResultEnum.BANK_CARD_IS_NULL.getName());
                 accountCheckingException.setHandleType(HandleTypeEnum.BOTH_ERROR.getIndex());
             }
             String bankCardNO = privacyMasks.decryptPrivacy(bankCard.getBankAccountNo());
             if( !bankCardNO.substring(bankCardNO.length() - 4,bankCardNO.length()).equals(accountCheckingRecharge.getBankAccountNo().substring(accountCheckingRecharge.getBankAccountNo().length() - 4 , accountCheckingRecharge.getBankAccountNo().length()))){
                 accountCheckingException.setHandleType(HandleTypeEnum.NORMAL.getIndex());
                 errors.add(CheckResultEnum.BANK_CORD_NO_ERROR.getName());
             }
         }

         //平台用户编号验证
         {
             AccountBase accountBase = accountBaseMapperExt.selectByPrimaryKey(rechargeOrder.getAccountId());
             if( !accountCheckingRecharge.getPlatformUserNo().equals(accountBase.getAccountNo())){
                 errors.add(CheckResultEnum.PLATFORM_USER_NO_ERROR.getName());
                 accountCheckingException.setHandleType(HandleTypeEnum.BOTH_ERROR.getIndex());
             }
         }


         return submit(accountCheckingRecharge,accountCheckingException,rechargeOrder,errors,checkDate);
    }

    private AccountCheckingException submit(AccountCheckingRecharge accountCheckingRecharge, AccountCheckingException accountCheckingException, RechargeOrder rechargeOrder, List<String> errors, String checkDate){

        if( null != errors && errors.size() > 0 ){
            accountCheckingException.setStatus(Byte.valueOf("1"));
            accountCheckingException.setBusinessType(Byte.valueOf("08"));
            accountCheckingException.setOrderNo(accountCheckingRecharge.getRechargeOrderNo());
            accountCheckingException.setCheckingType(Byte.valueOf("1"));
            accountCheckingException.setCheckingRecordId(accountCheckingRecharge.getCheckingRecordId());
            accountCheckingException.setCheckingDetailId(accountCheckingRecharge.getId());   //这个字段没用
            accountCheckingException.setPlatformRecordId((null == rechargeOrder) ? null : rechargeOrder.getId());
            accountCheckingException.setCreateTime(new Date());
            accountCheckingException.setBillDate(checkDate);
            accountCheckingException.setDescription(errors.toString());
            
            return accountCheckingException;
        }
        return null;
    }

    @Override
    public AccountCheckingRecharge parse(Long recordId, String content) {
        //0充值时间1平台商编2支付公司代码3平台请求流水号4充值订单编号5业务类型6金额7币种8会员编号9平台用户编号10银行卡号11银行编码12支付方式13到账金额14备注
        if (content == null || "".equals(content))
            return null;
        String[] sArr = content.split(",");
        AccountCheckingRecharge record = new AccountCheckingRecharge();
        record.setRechargeTime(DateUtil.parseT(sArr[0]));
        record.setPlatformMerchantNo(sArr[1]);
        record.setPayChannelCode(sArr[2]);
        record.setPlatformRequestNo(sArr[3]);
        record.setRechargeOrderNo(sArr[4]);
        record.setBusinessType(Byte.valueOf(sArr[5]));
        record.setAmount(BigDecimal.valueOf(Double.valueOf(sArr[6])));
        record.setAmonnt("人民币"); //7-人民币
        record.setMemberNo(sArr[8]);
        record.setPlatformUserNo(sArr[9]);
        record.setBankAccountNo(sArr[10]);
        record.setBankCode(sArr[11]);
        record.setPayType(Byte.valueOf(sArr[12]));
        record.setArrivalAmount(BigDecimal.valueOf(Double.valueOf(sArr[13])));
        record.setCreateTime(new Date());

        if (!content.endsWith(","))
            record.setRemark(sArr[14]);

        record.setStatus((byte) 1); // 1待处理
        record.setCheckingRecordId(recordId);

        // 过滤掉线下充值记录
        if (record.getPayType().equals((byte)3)) {
            return null;
        }


        return record;
    }

    @Override
    public void save(List<AccountCheckingRecharge> list) {
        if (list == null || list.isEmpty())
            return;
        //accountCheckingRechargeMapperExt.insertBatch(list);
        for(AccountCheckingRecharge accountCheckingRecharge : list){
            accountCheckingRechargeMapperExt.insert(accountCheckingRecharge);
        }
    }

    @Override
    public void deleteCheckRecord(Long recordId) {
        accountCheckingRechargeMapperExt.deleteByRecordId(recordId);
    }

    @Override
    public void extendBusiness(Long checkRecordId) {
    	//暂无业务
    }

    @Override
    public void batchUpdateCheckDetailStatus(Long checkRecordId, Byte status) {
        accountCheckingRechargeMapperExt.updateStatusByRecordId(checkRecordId,status);
    }

	@Override
	public void deleteAllCheckSuccessBankOrder(Long checkRecordId) {
        accountCheckingRechargeMapperExt.deleteByRecordId(checkRecordId);
	}
}
